import os
import cv2
import numpy as np

def get_image_paths(directory):
    image_extensions = {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff'}
    image_paths = []

    for root, dirs, files in os.walk(directory):
        for file in files:
            if os.path.splitext(file)[1].lower() in image_extensions:
                image_paths.append(os.path.abspath(os.path.join(root, file)))

    return image_paths

# 筛选矩形轮廓并计算面积
def is_rectangle(cnt, params1):
    # 获取最小外接矩形
    rect = cv2.minAreaRect(cnt)
    width, height = rect[1]
    # print(width, height)
    # 确保宽高比在一定范围内（不是正方形）
    aspect_ratio = max(width, height) / min(width, height)

    # 判断是否为矩形（宽高比在1到2之间）
    return params1["min_ratio"] < aspect_ratio < params1["max_ratio"]

# 找到与 group_a 和 group_b 相关的点
def find_and_add_missing_points(group_a, group_b):
    for point_a in group_a:
        closest_point = None
        min_distance = float('inf')

        for point_b in group_b:
            # 检查 x 值差异
            if abs(point_a[0] - point_b[0]) <= 10:
                # 计算 y 坐标差异
                distance = np.sqrt((point_a[0] - point_b[0]) ** 2 + (point_a[1] - point_b[1]) ** 2)
                if distance < min_distance:
                    min_distance = distance
                    closest_point = point_b

        # 如果找到最近的点，补充到对应的组
        if closest_point is not None and closest_point not in group_a:
            group_a.append(closest_point)

def line_intersection(p1, p2, p3, p4):
    """
    计算两条直线的交点

    :param p1: 直线1的第一个点 (x1, y1)
    :param p2: 直线1的第二个点 (x2, y2)
    :param p3: 直线2的第一个点 (x3, y3)
    :param p4: 直线2的第二个点 (x4, y4)
    :return: 交点坐标 (x, y)，如果不相交则返回 None
    """

    x1, y1 = p1
    x2, y2 = p2
    x3, y3 = p3
    x4, y4 = p4

    # 计算直线的斜率和截距
    denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)

    # 检查是否平行
    if denom == 0:
        return None  # 两条直线平行或重合

    # 计算交点坐标
    x = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / denom
    y = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / denom

    return (x, y)


def get_area_around_point(img, ori_img, pnt, range_size=25, range_size2=15):
    """
    获取给定点周围的图像区域
        #50  40
    :param img: 输入图像
    :param pnt: 点坐标 (x, y)
    :param range_size: 范围大小
    :return: 指定区域的图像
    """

    x, y = pnt
    left = int(max(x - range_size, 0))
    right = int(min(x + range_size, img.shape[1]))
    top = int(max(y - range_size2, 0))
    bottom = int(min(y + range_size2, img.shape[0]))

    # 裁剪图像
    area = np.sum(img[top:bottom, left:right])

    max_area = 4 * range_size * range_size2 * 255  # 矩形全为白的面积理论最大值
    # 在原图上绘制红色矩形框
    cv2.rectangle(ori_img, (left, top), (right, bottom), (0, 0, 255), 2)  # 红色框
    # cv2.imwrite('../score_plus/saved_image5.jpg', ori_img)

    return area, max_area


def number_to_letter(num):
    """
    将数字转换为对应的字母

    :param num: 输入的数字 (1-26)
    :return: 对应的字母
    """
    if 1 <= num <= 26:
        return chr(num + 64)  # 'A' 的 ASCII 码是 65
    else:
        return None  # 超出范围的处理

def solve_1(img_path, standard_answers, subjectCode, studentId, paperId, answerQrcode, parent_answer_id, vis=False):
    image = cv2.imread(img_path)
    height, width, _ = image.shape
    question_type = answerQrcode[0]
    processing_states = [18, 1, 13, 12, 7, 8, 2, 3, 4, 5, 6, 14, 15, 16, 11, 17, 19, 20, 21, 10]

    # processing_states = [10]  # 定义不同的处理状态
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    for state in processing_states:
        if state == 21:
            params1 = {
                "min_area": 220,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 3.5,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 220,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 20,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.4,  # 选项的填涂面积最小阈值
            }
            blurred = gray

            # 降噪 - 使用高斯模糊
            blurred_denoised = cv2.GaussianBlur(blurred, (13, 13), 3)  # 高斯模糊
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 94)
            # cv2.imwrite('../score_plus/saved_image1.jpg', thresh2)

            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((17, 17), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)
        elif state == 18:
            params1 = {
                "min_area": 220,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 3.5,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 220,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 20,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.4,  # 选项的填涂面积最小阈值
            }
            blurred = gray

            # 降噪 - 使用高斯模糊
            blurred_denoised = cv2.GaussianBlur(blurred, (13, 13), 3)  # 高斯模糊
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 94)
            # cv2.imwrite('../score_plus/saved_image1.jpg', thresh2)

            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((17, 17), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)

        elif state == 20:
            params1 = {
                "min_area": 220,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 3.5,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 220,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 20,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.4,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            # 降噪 - 使用高斯模糊
            blurred_denoised = cv2.GaussianBlur(blurred, (13, 13), 2)  # 高斯模糊
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 94)
            # cv2.imwrite('../score_plus/saved_image1.jpg', thresh2)

            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((17, 17), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)
        elif state == 19:
            params1 = {
                "min_area": 220,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 3.5,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 220,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 20,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.4,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            # 降噪 - 使用高斯模糊
            blurred_denoised = cv2.GaussianBlur(blurred, (13, 13), 3)  # 高斯模糊
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 94)
            # cv2.imwrite('../score_plus/saved_image1.jpg', thresh2)

            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((17, 17), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)
        elif state == 13:
            params1 = {
                "min_area": 220,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 3.5,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 220,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 20,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.4,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            # 降噪 - 使用高斯模糊
            blurred_denoised = cv2.GaussianBlur(blurred, (13, 13), 2)  # 高斯模糊
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 101)
            # cv2.imwrite('../score_plus/saved_image1.jpg', thresh2)

            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((17, 17), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)
        elif state == 17:
            params1 = {
                "min_area": 220,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 2.0,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 220,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 20,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.4,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            # 降噪 - 使用高斯模糊
            blurred_denoised = cv2.GaussianBlur(blurred, (13, 13), 2)  # 高斯模糊，核大小为 (7, 7)
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                            cv2.THRESH_BINARY_INV, 99, 101)
            # cv2.imwrite('../score_plus/saved_image1.jpg', thresh2)

            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((17, 17), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)
        elif state == 2:
            # print(2)
            params1 = {
                "min_area": 100,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比
                "max_ratio": 5.0,  # 判断矩形的最大长宽比
                "diff_area": 200,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 25,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 10,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 200000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.5,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            # 降噪 - 使用高斯模糊
            blurred_denoised = cv2.GaussianBlur(blurred, (7, 7), 3)  # 高斯模糊，核大小为 (7, 7)
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 7)
            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((19, 19), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)

        elif state == 3:
            # print(3)
            params1 = {
                "min_area": 200,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 3.0,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 200,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 25,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 10,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.5,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            # 降噪 - 使用高斯模糊
            blurred_denoised = cv2.GaussianBlur(blurred, (7, 7), 3)  # 高斯模糊，核大小为 (7, 7)
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 7)
            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((21, 21), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)
        elif state == 4:
            params1 = {
                "min_area": 100,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比
                "max_ratio": 5.0,  # 判断矩形的最大长宽比
                "diff_area": 200,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 25,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 10,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 300000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.5,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            blurred_denoised = cv2.GaussianBlur(blurred, (7, 7), 3)  # 高斯模糊，核大小为 (7, 7)
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 7)
            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((19, 19), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)

        elif state == 7:
            # print(1)
            params1 = {
                "min_area": 200,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 3.0,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 200,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 10,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.5,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            blurred_denoised = cv2.GaussianBlur(blurred, (7, 7), 3)  # 高斯模糊，核大小为 (7, 7)
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 7)
            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((19, 19), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)
        elif state == 5:
            params1 = {
                "min_area": 260,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 1.8,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 200,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 25,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 10,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.5,  # 选项的填涂面积最小阈值
            }
            blurred = cv2.GaussianBlur(gray, (13, 13), 0)
            thresh = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
            # 进行去噪，使用形态学操作（例如开运算）
            kernel = np.ones((7, 7), np.uint8)
            thresh_denoised2 = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
            # cv2.imwrite('../score_plus/saved_image7.jpg', thresh_denoised)
        elif state == 6:
            # print(6)
            params1 = {
                "min_area": 600,  # 标记的最小面积阈值
                "min_ratio": 1.6,  # 判断矩形的最小长宽比
                "max_ratio": 3.0,  # 判断矩形的最大长宽比
                "diff_area": 200,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 25,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 10,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 300000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.4,  # 选项的填涂面积最小阈值
            }
            blurred = cv2.GaussianBlur(gray, (13, 13), 0)
            thresh = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
            # 进行去噪，使用形态学操作（例如开运算）
            kernel = np.ones((7, 7), np.uint8)
            thresh_denoised2 = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
            # cv2.imwrite('../score_plus/saved_image7.jpg', thresh_denoised)
        elif state == 8:
            params1 = {
                "min_area": 200,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 3.5,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 205,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 10,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0, # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.5,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            #去噪
            blurred_denoised = cv2.GaussianBlur(blurred, (7, 7), 3)  # 高斯模糊，核大小为 (7, 7)
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 7)
            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((21, 21), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)
        elif state == 9:
            params1 = {
                "min_area": 200,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 3.5,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 220,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 10,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0, # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.6,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            #去噪
            blurred_denoised = cv2.GaussianBlur(blurred, (7, 7), 3)  # 高斯模糊，核大小为 (7, 7)
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 7)
            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((21, 21), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)
        elif state == 10:
            params1 = {
                "min_area": 200,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 3.5,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 220,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 20,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.5,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            #去噪
            blurred_denoised = cv2.GaussianBlur(blurred, (9, 9), 3)  # 高斯模糊，核大小为 (7, 7)
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 75)
            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((17, 17), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)

        elif state == 11:
            params1 = {
                "min_area": 200,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 3.5,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 220,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 20,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.5,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            #去噪
            blurred_denoised = cv2.GaussianBlur(blurred, (7, 7), 3)  # 高斯模糊，核大小为 (7, 7)
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 7)
            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((17, 17), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)
        elif state == 12:
            params1 = {
                "min_area": 200,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 3.5,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 220,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 20,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.7,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            #去噪
            blurred_denoised = cv2.GaussianBlur(blurred, (7, 7), 3)  # 高斯模糊，核大小为 (7, 7)
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 7)
            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((17, 17), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)
        elif state == 1:
            params1 = {
                "min_area": 200,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 3.5,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 220,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 20,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.5,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            #去噪
            blurred_denoised = cv2.GaussianBlur(blurred, (7, 7), 3)  # 高斯模糊，核大小为 (7, 7)
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 7)
            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((17, 17), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)
        elif state == 14:
            params1 = {
                "min_area": 200,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 3.0,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 160,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 20,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.5,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            #去噪
            blurred_denoised = cv2.GaussianBlur(blurred, (7, 7), 3)  # 高斯模糊，核大小为 (7, 7)
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 7)
            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((17, 17), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)

        elif state == 15:
            params1 = {
                "min_area": 200,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 5.0,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 230,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 20,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.5,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            #去噪
            blurred_denoised = cv2.GaussianBlur(blurred, (7, 7), 3)  # 高斯模糊，核大小为 (7, 7)
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 7)
            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((17, 17), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)
        elif state == 16:
            params1 = {
                "min_area": 200,  # 标记的最小面积阈值
                "min_ratio": 0.5,  # 判断矩形的最小长宽比  #标记点
                "max_ratio": 5.0,  # 判断矩形的最大长宽比  #标记点
                "diff_area": 160,  # 用于查找标记的面积差值允许范围，当两两面积之差小于diff_area则归为标记
                "y_threshold": 10,  # y轴距离阈值，用于判断多个点是否在同一水平直线上，y_threshold为多个点的y值差值的最大阈值
                "x_threshold": 25,  # x轴距离阈值，用于处理过滤掉超过2个标记但不是横向标记的问题（那正常的2标记横向两点的x轴与问题点集进行过滤）
                "min_error": 20,  # 纵向来看，左右两边的两两标记间距之间的差距允许最小误差
                "threshold_2": 500000,  # 用于判断选择题是否填涂，当某位置的面积小于max_area - threshold_2时表示未填涂，max_area为所有位置最大面积
                "threshold_3": 150000,  # 用于判断选择题是否填涂，从原始填涂的面积角度直接判断的最小面积阈值
                "threshold_4": 0,  # 用于判断是否存在选项，如果没有选项则视为指定列不存在问题
                "area_ratio": 0.5,  # 选项的填涂面积最小阈值
            }
            blurred = gray
            #去噪
            blurred_denoised = cv2.GaussianBlur(blurred, (7, 7), 3)  # 高斯模糊，核大小为 (7, 7)
            thresh2 = cv2.adaptiveThreshold(blurred_denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 99, 7)
            # 定义膨胀的结构元素
            kernel_32 = np.ones((0, 0), np.uint8)  # 可以调整大小
            # 进行膨胀操作
            dilated2 = cv2.dilate(thresh2, kernel_32, iterations=1)
            thresh2 = dilated2
            kernel12 = np.ones((11, 11), np.uint8)
            kernel2 = np.ones((17, 17), np.uint8)
            thresh_closed2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel12)
            thresh_denoised2 = cv2.morphologyEx(thresh_closed2, cv2.MORPH_OPEN, kernel2)
            # cv2.imwrite('../score_plus/saved_image6.jpg', thresh_denoised2)

        if subjectCode == "999" and answerQrcode == "11":
            group_a = [(102, 552), (627, 551), (715, 551), (889, 551), (364, 552), (540, 551), (277, 552), (1240, 550), (802, 551), (189, 552), (1153, 550), (1066, 550), (1327, 550), (453, 551), (976, 550)]
            group_b = [(801, 112), (627, 113), (540, 113), (453, 113), (364, 113), (276, 113), (189, 113), (713, 113), (1326, 113), (1239, 113), (1152, 113), (1065, 113), (976, 113), (101, 113), (888, 113)]
            h_list = [[(1391, 471), (46, 474)], [(44, 233), (1390, 230)], [(1391, 514), (46, 517)], [(45, 392), (1391, 389)], [(45, 434), (1391, 430)], [(1390, 271), (44, 274)], [(1390, 313), (45, 317)], [(44, 192), (1390, 188)]]

        elif subjectCode == "999" and answerQrcode == "21":
            group_a = [(365, 751), (190, 753), (628, 751), (977, 750), (1066, 750), (454, 751), (1328, 750), (1153, 750), (103, 752), (715, 750), (278, 752), (890, 751), (542, 751), (803, 750), (1240, 750)]
            group_b = [(1239, 109), (276, 110), (189, 110), (627, 110), (888, 109), (1064, 109), (802, 110), (714, 110), (540, 110), (364, 110), (102, 110), (1152, 109), (975, 109), (452, 109), (1326, 109)]
            h_list = [[(1388, 717), (44, 718)], [(1388, 591), (44, 592)], [(44, 514), (1387, 513)], [(44, 388), (1387, 386)],[(1387, 429), (44, 431)], [(44, 309), (1387, 307)], [(1386, 224), (44, 225)], [(1388, 634), (44, 635)],[(1387, 266), (44, 268)], [(44, 473), (1387, 472)], [(43, 183), (1386, 181)], [(44, 678), (1388, 676)]]

        elif subjectCode == "856" and answerQrcode == "11":
            group_a = [(1300, 510), (1394, 510), (138, 512), (717, 511), (411, 512), (1483, 510), (229, 512), (1206, 510),(995, 511), (321, 512), (505, 512), (812, 511), (627, 511), (1115, 510), (901, 511)]
            group_b = [(507, 1290), (901, 1289), (812, 1289), (719, 1289), (229, 1290), (1301, 1289), (1207, 1289),(1396, 1289), (412, 1290), (1485, 1288), (321, 1290), (139, 1290), (1116, 1289), (995, 1289),(628, 1289)]
            h_list = [[(1557, 723), (65, 726)], [(1557, 651), (65, 653)], [(1557, 1006), (65, 1007)],[(65, 794), (1557, 792)], [(65, 1218), (1557, 1215)], [(1558, 1146), (65, 1149)],[(1557, 1074), (65, 1076)], [(1557, 865), (65, 867)]]
        elif subjectCode == "856" and answerQrcode == "52":
            group_a = [(132, 243), (218, 243), (303, 242), (389, 242), (475, 242), (586, 242), (672, 242), (757, 241),(842, 242), (928, 242), (1040, 241), (1126, 241), (1211, 241), (1296, 241), (1380, 241),(1492, 241), (1577, 241), (1667, 240), (1752, 240), (1837, 239)]
            group_b = [(133, 573), (218, 573), (303, 572), (389, 572), (475, 572), (587, 571), (672, 571), (756, 571),(842, 570), (928, 571), (1040, 570), (1126, 570), (1211, 570), (1296, 570), (1381, 570),(1492, 570), (1576, 570), (1667, 570), (1752, 570), (1837, 569)]
            h_list = [[(64, 355), (1906, 351)], [(64, 410), (1905, 407)], [(64, 462), (1905, 458)],[(64, 516), (1906, 514)]]



        group_a = sorted(group_a, key=lambda point: point[0])
        group_b = sorted(group_b, key=lambda point: point[0])
        # 首先对内部的小列表按 x 值排序
        for sublist in h_list:
            sublist.sort(key=lambda point: point[0])

        # 然后对外部列表按小列表第一个元素的 y 值排序
        h_list.sort(key=lambda sublist: sublist[0][1])

        if vis:
            print(f"group_a: {group_a}")
            print(f"group_b: {group_b}")
            print(f"h_list: {h_list}")
        # 存储需要删除的索引
        to_delete = []
        # dist_lst表示每行之间的距离
        dist_lst = np.zeros(len(h_list) - 1)
        for idx in range(len(h_list) - 1):
            dist_lst[idx] = h_list[idx + 1][0][1] - h_list[idx][0][1]
            if dist_lst[idx] == 0:
                to_delete.append(idx)
        # 从后向前删除，以避免索引变化导致的问题
        for idx in sorted(to_delete, reverse=True):
            del h_list[idx]
        # 移除所有 0 的元素
        dist_lst = [item for item in dist_lst if item != 0.0]
        # 拿第一行与第二行之间的间距作为对比标准
        n_answer_lst = []
        view = dist_lst[0]
        now_list = [1]
        for idx in range(len(h_list) - 1):
            if abs(dist_lst[idx] - view) <= params1["min_error"]:
                now_list.append(idx + 2)
            else:
                n_answer_lst.append(now_list)
                now_list = []  # 重置now_list
                # idx + 2只有在now_list为空时才添加，因为now_list已经重置为空
                now_list.append(idx + 2)
        if len(now_list) != 0:
            n_answer_lst.append(now_list)

        # 检查所有子列表的长度是否相等
        all_equal = all(len(group) == len(n_answer_lst[0]) for group in n_answer_lst)
        if all_equal:
            pass
        else:
            continue
        # print(f"n_answer_list: {n_answer_lst}")

        # 答题卡的题数，选项的个数
        n_question, n_answer = len(group_a), len(h_list)
        # print(f"n_question: {n_question}, n_answer: {n_answer}")

        answers = []
        max_area = 0
        area_sums = np.zeros((n_question, n_answer))
        for idx in range(n_question):
            for l_idx, now_list in enumerate(n_answer_lst):
                for h in range(len(now_list)):
                    pnt = line_intersection(h_list[now_list[h] - 1][0], h_list[now_list[h] - 1][1], group_a[idx], group_b[idx])
                    area, m_area = get_area_around_point(thresh_denoised2, image, pnt)
                    if vis:
                        print(f"ratio: {area / m_area}")
                    max_area = max(max_area, area)
                    area_sums[idx][now_list[h] - 1] = area
                    if vis:
                        print(f"n_question_{idx + 1}, n_answer_{h + 1}: {area}")

        threshold_2 = params1["threshold_2"]
        threshold_3 = params1["threshold_3"]
        threshold_4 = params1["threshold_4"]
        if vis:
            print(f"max_area: {max_area}, {max_area - threshold_2}")
        # lock = False  # 判断是否是多选题

        for l_idx, now_list in enumerate(n_answer_lst):
            for idx in range(n_question):
                pnt2 = []
                answer = ""
                judge = False  # 判断是否是空白的
                lock = False  # 判断是否是多选题
                for h in range(len(now_list)):
                    now_area = area_sums[idx][now_list[h] - 1]
                    # print(f"now_list: {now_list}")
                    # print(f"idx: {idx}, h: {h}, now_area: {now_area}")
                    pnt = line_intersection(h_list[now_list[h] - 1][0], h_list[now_list[h] - 1][1], group_a[idx],
                                            group_b[idx])

                    area, m_area = get_area_around_point(thresh_denoised2, image, pnt)
                    ratio = area / m_area
                    # 提取每个元组的第三个元素（字母）
                    letters = [item[2] for item in standard_answers]

                    # 使用set来找出所有不同的字母
                    unique_letters = set(letters)
                    # 对不同字母进行排序
                    sorted_unique_letters = sorted(unique_letters)
                    # 找到排序后的最后一个字母
                    last_letter = sorted_unique_letters[-1]
                    # 将最后一个字母转换成数字
                    number = ord(last_letter) - ord('A') + 1
                    # print(f"字母有:{unique_letters}")
                    # # 打印不同字母的种类数量
                    # print(f"字幕的种类有 {len(unique_letters)} 种")
                    if len(now_list) != number:
                        # print("行数识别不符号要求")
                        break

                    if ratio >= params1["area_ratio"]:
                        if len(now_list) == 2 and question_type == 3:  # 判断题
                            pnt2.append(pnt)
                            if h == 0:
                                answer += "T"
                            elif h == 1:
                                answer += "F"
                        else:
                            tmp = number_to_letter(h + 1)
                            if tmp is not None:
                                pnt2.append(pnt)
                                if answer:  # 如果 answer 不为空
                                    answer += ","  # 添加逗号和空格
                                answer += tmp  # 添加字母到 answer

                    if now_area >= threshold_4:
                        judge = True

                if lock == True:
                    break

                if idx + l_idx * n_question < len(standard_answers):
                    if len(standard_answers[idx + l_idx * n_question][2]) == 1 and len(answer) != 1:
                        if state != 10:
                            lock = True
                            break
                        else:
                            answer = ''

                if question_type != "2" and len(answer) > 1:
                    lock = True
                    break
                # print(state)
                if judge:
                    # print(state)
                    # print(f"answer:{answer}")
                    # print(f"idx:{idx+l_idx*n_question}")
                    # print(f"len(standard_answers):{len(standard_answers)}")
                    if idx + l_idx * n_question < len(standard_answers):
                        if answer == "":
                            pnt2 = []
                            answers.append((standard_answers[idx + l_idx * n_question][0], subjectCode, studentId, standard_answers[idx + l_idx * n_question][2], paperId, pnt2, None, standard_answers[idx + l_idx * n_question][1]))
                        else:
                            answers.append((standard_answers[idx + l_idx * n_question][0], subjectCode, studentId, standard_answers[idx + l_idx * n_question][2], paperId, pnt2, answer, standard_answers[idx + l_idx * n_question][1]))
                    else:
                        pass
                else:
                    break
            if lock:
                lock = True
                break
        if lock:
            continue
        if vis:
            cv2.imshow('Marked Image', image)
            cv2.imwrite('test/Marked_Image.png', image)
            cv2.waitKey(0)
            cv2.destroyAllWindows()

        return answers


